package com.guchenbo.lssp.server;

import com.guchenbo.lssp.domain.LivySessionReq;
import com.guchenbo.lssp.domain.LivySessionRes;
import com.guchenbo.lssp.domain.LivyStatementReq;
import com.guchenbo.lssp.domain.LivyStatementRes;
import com.guchenbo.lssp.exception.SessionException;
import com.guchenbo.lssp.pool.PooledSession;
import com.guchenbo.lssp.pool.SessionSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * 为了兼容livy接口，这里保持和livy的请求一致
 *
 * @author guchenbo
 */
@ControllerAdvice(assignableTypes = SessionController.class)
@RestController
@RequestMapping("/lssp/sessions")
public class SessionController {
    protected static final Logger log = LoggerFactory.getLogger(SessionController.class);

    @Resource
    private SessionSource sessionSource;

    @PostMapping
    public LivySessionRes createSession(@RequestBody LivySessionReq sessionReq) throws SessionException {
        PooledSession session = null;
        try {
            log.info("createSession use lssp server");
            session = sessionSource.getSession();
            log.info("get session {}", session.getId());
            LivySessionRes sessionRes = new LivySessionRes();
            sessionRes.setId(session.getSessionId());
            return sessionRes;
        } catch (Exception e) {
            log.error("createSession error", e);
            throw e;
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    @GetMapping
    public LivySessionRes getSessions() {
        log.info("getSessions");
        // 默认返回空
        return new LivySessionRes();
    }

    @DeleteMapping(value = "/{sessionId}")
    public void killSession(@PathVariable("sessionId") Long sessionId) {
        sessionSource.getLivyHelper().livyKillSession(sessionId);
    }

    @GetMapping(value = "/{sessionId}")
    public void checkSession(@PathVariable Long sessionId) {
        sessionSource.getLivyHelper().livyCheckSession(sessionId);
    }

    @PostMapping(value = "/{sessionId}/statements")
    public LivyStatementRes createStatement(@PathVariable("sessionId") Long sessionId,
                    @RequestBody LivyStatementReq statementReq) {
        return sessionSource.getLivyHelper().livyCreateStatement(sessionId, statementReq);
    }

    @GetMapping(value = "/{sessionId}/statements/{statementId}")
    public LivyStatementRes queryStatement(@PathVariable("sessionId") Long sessionId,
                    @PathVariable("statementId") Long statementId) {
        return sessionSource.getLivyHelper().livyQueryStatement(sessionId, statementId);
    }

    @ExceptionHandler(HttpClientErrorException.class)
    @ResponseBody
    public ResponseEntity<String> handleHttpClientException(HttpClientErrorException e, HttpServletRequest request) {
        log.error("统一异常LssPServer捕捉 {}", request.getRemoteAddr(), e);
        return new ResponseEntity<>(e.getResponseBodyAsString(), HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(HttpServerErrorException.class)
    @ResponseBody
    public ResponseEntity<String> handleHttpServerException(HttpServerErrorException e, HttpServletRequest request) {
        log.error("统一异常LssPServer捕捉 {}", request.getRemoteAddr(), e);
        return new ResponseEntity<>(e.getResponseBodyAsString(), HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseEntity<Void> handleException(Exception e, HttpServletRequest request) {
        log.error("统一异常LssPServer捕捉 {}", request.getRemoteAddr(), e);
        return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
